package com.wonders.framework.dao.transformer;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.property.ChainedPropertyAccessor;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.ResultTransformer;

import com.wonders.framework.exception.FrameworkException;

/**
 * 数据查询对象转换器
 * 
 * @author WuBin
 * 
 */
public class BeanTransformer implements ResultTransformer {

	private final Class resultClass;

	private Setter[] setters;

	private PropertyAccessor propertyAccessor;

	public BeanTransformer(Class resultClass) {
		if (resultClass == null)
			throw new IllegalArgumentException("resultClass cannot be null");
		this.resultClass = resultClass;
		propertyAccessor = new ChainedPropertyAccessor(new PropertyAccessor[] {
				PropertyAccessorFactory.getPropertyAccessor(resultClass, null),
				PropertyAccessorFactory.getPropertyAccessor("field") });
	}

	public Object transformTuple(Object[] tuple, String[] aliases) {
		Object result;
		String key = "";
		Object value;
		try {
			result = resultClass.newInstance();
			for (int i = 0; i < aliases.length; i++) {
				String alias = aliases[i];
				String firstCh = alias.substring(0, 1);
				key = alias;
				// get property name
				if (firstCh.equals(firstCh.toUpperCase())) {
					alias = columnNameToPropertyName(alias);
					key = alias;
				}
				// get value
				value = tuple[i];
				Class expectedClass = null;
				try {
					expectedClass = PropertyUtils
							.getPropertyType(result, alias);
					if (expectedClass == null) {
						continue;
					}
				} catch (NoSuchMethodException ex) {
					continue;
				}
				/*
				 * try { Field field = this.resultClass.getDeclaredField(alias);
				 * expectedClass = field.getType(); } catch
				 * (NoSuchFieldException ex) { continue; }
				 */
				// 类型转换
				if (tuple[i] != null && tuple[i] instanceof BigDecimal) {
					BigDecimal columnValue = (BigDecimal) tuple[i];
					if (expectedClass.equals(Long.class)) {
						value = Long.valueOf(columnValue.longValue());

					} else if (expectedClass.equals(Integer.class)) {
						value = Integer.valueOf(((BigDecimal) tuple[i])
								.intValue());
					} else if (expectedClass.equals(Boolean.class)) {
						int v = columnValue.intValue();
						if (v == 0) {
							value = false;
						} else {
							value = true;
						}
					} else if (expectedClass.equals(String.class)) {
						value = columnValue.toString();
					} else if (expectedClass.equals(BigInteger.class)) {
						value = columnValue.toBigInteger();
					}
				}
				// 赋值
				PropertyUtils.setProperty(result, key, value);
			}// end of for
		} catch (InstantiationException e) {
			throw new HibernateException("Could not instantiate resultclass: "
					+ resultClass.getName());
		} catch (Exception e) {
			throw new FrameworkException("转换异常", e);
		}

		return result;
	}

	public String columnNameToPropertyName(String colName) {
		if (StringUtils.isBlank(colName)) {
			return StringUtils.EMPTY;
		}
		String colName2 = colName.toLowerCase();
		String[] cols = colName2.split("_");
		StringBuilder sb = new StringBuilder();
		sb.append(cols[0]);
		if (cols.length == 1) {
			return sb.toString();
		}

		for (int i = 1; i < cols.length; i++) {
			String col = cols[i];
			sb.append(col.substring(0, 1).toUpperCase());
			sb.append(col.substring(1));
		}
		return sb.toString();
	}

	public List transformList(List collection) {
		return collection;
	}

}
